home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-10-25 | 6.8 KB | 274 lines | [TEXT/MPS ] |
- {$P}
- {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
- { UPatch.inc1.p }
- { Copyright © 1985-1990 by Apple Computer, Inc. All rights reserved. }
-
- TYPE
- { System heap block record for PatchTrap }
- PTBlockPtr = ^PTBlock;
- PTBlock = RECORD
- Jmp: INTEGER;
- Routine: Ptr;
- END;
-
- { System heap block record for HeadPatch }
- TPBlockPtr = ^TPBlock;
- TPBlock = RECORD
- MoveL: INTEGER;
- OldTrapAddr: LONGINT;
- Jmp: INTEGER;
- Routine: Ptr;
- END;
-
- { System heap block record for Head1Patch }
- T1PBlockPtr = ^T1PBlock;
- T1PBlock = RECORD
- MoveParameter: LONGINT;
- MoveL: INTEGER;
- OldTrapAddr: LONGINT;
- Jmp: INTEGER;
- Routine: Ptr;
- END;
-
- FUNCTION NewPermPtr(logicalSize: Size): Ptr; { So we don't have to USE UMemory }
- EXTERNAL;
-
- {--------------------------------------------------------------------------------------------------}
- {$S MAMiniInit}
-
- PROCEDURE InitUPatch;
-
- BEGIN
- pPatchList := NIL; { Initialize the linked list of patches. }
- END;
-
- {--------------------------------------------------------------------------------------------------}
- {$S MAPatchRes}
-
- FUNCTION AllocBlock(blockSize: INTEGER;
- theTrapNum: INTEGER;
- VAR thePatch: TrapPatch): Ptr;
-
- { If blockSize is greater than zero, AllocBlock allocates a non-
- relocatable block in the system heap, of size blockSize. It then
- fills all fields of thePatch. If blockSize is zero, then no block
- is allocated and AllocBlock fills fields of thePatch. }
-
- VAR
- theBlock: Ptr;
-
- BEGIN
- IF blockSize > 0 THEN
- BEGIN
- IF qNeedsROM128K | gConfiguration.hasROM128K THEN
- theBlock := NewPermPtr(blockSize)
- ELSE
- theBlock := NewPtrSys(blockSize);
- END
- ELSE
- theBlock := NIL;
-
- WITH thePatch DO { get thePatch in a register for speed }
- BEGIN
- jmpPtr := theBlock;
- OldTrapAddr := NGetTrapAddress(theTrapNum, GetTrapType(theTrapNum));
- trapNum := theTrapNum;
- nextPatch := pPatchList;
- END;
- pPatchList := @thePatch;
- AllocBlock := theBlock;
- END;
-
- {--------------------------------------------------------------------------------------------------}
- {$S MAPatchRes}
-
- FUNCTION PatchTrap(VAR thePatch: TrapPatch;
- theTrapNum: INTEGER;
- theRoutine: Ptr): OSErr;
-
- VAR
- patchBlock: PTBlockPtr;
-
- BEGIN
- IF qNeedsROM128K | gConfiguration.hasROM128K THEN
- BEGIN
- { On 128K ROMs, setup the patch record and the trap address }
- patchBlock := PTBlockPtr(AllocBlock(0, theTrapNum, thePatch));
- NSetTrapAddress(ORD4(theRoutine), theTrapNum, GetTrapType(theTrapNum));
- PatchTrap := noErr;
- END
- ELSE
- BEGIN
-
- { Allocate the system heap block, and fill thePatch }
- patchBlock := PTBlockPtr(AllocBlock(SIZEOF(PTBlock), theTrapNum, thePatch));
-
- IF patchBlock <> NIL THEN
- BEGIN
- { Stuff the code into the block }
- WITH patchBlock^ DO
- BEGIN
- Jmp := $4EF9; { JMP #Routine }
- Routine := theRoutine;
- END;
-
- { Set the trap address to the block of code in the system heap }
- NSetTrapAddress(ORD4(patchBlock), theTrapNum, GetTrapType(theTrapNum));
- END;
-
- PatchTrap := MemError;
- END;
- END;
-
- {--------------------------------------------------------------------------------------------------}
- {$S MAPatchRes}
-
- FUNCTION HeadPatch(VAR thePatch: TrapPatch;
- theTrapNum: INTEGER;
- theRoutine: Ptr): OSErr;
-
- VAR
- patchBlock: TPBlockPtr;
-
- BEGIN
- { Allocate the system heap block, and fill thePatch }
- patchBlock := TPBlockPtr(AllocBlock(SIZEOF(TPBlock), theTrapNum, thePatch));
-
- IF patchBlock <> NIL THEN
- BEGIN
- { Stuff the code into the block }
- WITH patchBlock^ DO
- BEGIN
- MoveL := $2F3C; { MOVE.L #OldTrapAddr,-(SP) }
- OldTrapAddr := thePatch.OldTrapAddr;
- Jmp := $4EF9; { JMP #Routine }
- Routine := theRoutine;
- END;
-
- { Set the trap address to the block of code in the system heap }
- NSetTrapAddress(ORD4(patchBlock), theTrapNum, GetTrapType(theTrapNum));
- END;
- HeadPatch := MemError;
- END;
-
- {--------------------------------------------------------------------------------------------------}
- {$S MAPatchRes}
-
- FUNCTION Head1Patch(VAR thePatch: TrapPatch;
- theTrapNum: INTEGER;
- theRoutine: Ptr): OSErr;
-
- VAR
- patchBlock: T1PBlockPtr;
-
- BEGIN
- { Allocate the system heap block, and fill thePatch }
- patchBlock := T1PBlockPtr(AllocBlock(SIZEOF(T1PBlock), theTrapNum, thePatch));
-
- IF patchBlock <> NIL THEN
- BEGIN
- { Stuff the code into the block }
- WITH patchBlock^ DO
- BEGIN
- MoveParameter := $2F2F0004; { MOVE.L 4(SP),-(SP) }
- MoveL := $2F3C; { MOVE.L #OldTrapAddr,-(SP) }
- OldTrapAddr := thePatch.OldTrapAddr;
- Jmp := $4EF9; { JMP #Routine }
- Routine := theRoutine;
- END;
-
- { Set the trap address to the block of code in the system heap }
- NSetTrapAddress(ORD4(patchBlock), theTrapNum, GetTrapType(theTrapNum));
- END;
- Head1Patch := MemError;
- END;
-
- {--------------------------------------------------------------------------------------------------}
- {$S MAPatchRes}
-
- PROCEDURE UnpatchTrap(VAR thePatch: TrapPatch);
-
- VAR
- aPatch: TrapPatchPtr;
-
- BEGIN
- { Unlink the patch from the linked list of patches }
- IF @thePatch = pPatchList THEN
- pPatchList := thePatch.nextPatch
- ELSE
- BEGIN
- aPatch := pPatchList;
- WHILE aPatch^.nextPatch <> @thePatch DO
- BEGIN
- aPatch := aPatch^.nextPatch;
- IF aPatch = NIL THEN
- { Couldn't find thePatch, so don't try to unpatch it. }
- EXIT(UnpatchTrap);
- END;
- aPatch^.nextPatch := thePatch.nextPatch;
- END;
-
- WITH thePatch DO
- BEGIN
- { If the patch allocated a block in the system heap, deallocate it }
- jmpPtr := DisposeIfPtr(jmpPtr);
-
- { Restore the trap address }
- NSetTrapAddress(OldTrapAddr, trapNum, GetTrapType(trapNum));
- END;
-
- END;
-
- {--------------------------------------------------------------------------------------------------}
- {$S MAPatchRes}
-
- PROCEDURE UnpatchAll;
-
- BEGIN
- WHILE pPatchList <> NIL DO
- UnpatchTrap(pPatchList^);
- END;
-
- {--------------------------------------------------------------------------------------------------}
- {$S MAPatchRes}
-
- PROCEDURE EachPatchDo(FUNCTION DoToPatch(thePatchPtr: TrapPatchPtr): BOOLEAN);
-
- VAR
- aPatchPtr: TrapPatchPtr;
-
- BEGIN
- aPatchPtr := pPatchList;
-
- WHILE aPatchPtr <> NIL DO
- IF NOT DoToPatch(aPatchPtr) THEN
- aPatchPtr := aPatchPtr^.nextPatch
- ELSE
- LEAVE;
- END;
-
- {--------------------------------------------------------------------------------------------------}
- {$S MAPatchRes}
-
- PROCEDURE SetCallBack(targProc: ProcPtr; itsRefCon: Longint; theCallBackPtr: CallBackPtr);
-
- {
- 00000000: 2F17 '/.' MOVE.L (A7),-(A7) ; move old rtn address
- 00000002: 2F7C 1122 3344 '/|."3D' MOVE.L #$11223344,$0004(A7) ; plop refcon in
- 0004
- 0000000A: 4EF9 1122 3344 'N.."3D' JMP $11223344 ; shove off
- }
-
- BEGIN
- WITH theCallBackPtr^ DO
- BEGIN
- saveRtnAdd := $2F17;
- moveRefCon := $2F7C;
- refCon := itsRefCon;
- targOffset := $0004;
- jmpInst := $4EF9;
- jmpTarg := ORD(targProc);
- END;
- { ??? should we flush the processor cache at this point? }
- END;
-